package com.test.web.nettyserver;

import com.alibaba.fastjson.JSON;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.MemoryAttribute;
import io.netty.util.CharsetUtil;
import jdk.nashorn.internal.parser.JSONParser;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONValue;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;

@Slf4j
@Service
@ChannelHandler.Sharable
public class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> {


    @Autowired
    private DispatcherServlet dispatcherServlet;

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest)
            throws Exception {
        log.info("inbound");
        //检查http方法  get 和 post
        boolean flag = HttpMethod.GET.equals(fullHttpRequest.method())
                || HttpMethod.POST.equals(fullHttpRequest.method());
        if(flag && channelHandlerContext.channel().isActive()){
            log.info("request");
            // 将FullHttpRequest 转换成ServletRequest
            MockHttpServletRequest servletRequest = getRequest(fullHttpRequest);
            MockHttpServletResponse servletResponse = new MockHttpServletResponse();
            // 将 请求交给 dispathcherServlet 处理
            dispatcherServlet.service(servletRequest,servletResponse);
            // 返回响应结果
            FullHttpResponse response = getResponse(servletResponse);

            ChannelFuture writeFuture = channelHandlerContext.writeAndFlush(response);
            writeFuture.addListener(ChannelFutureListener.CLOSE);
        }
    }

    /**
     * 转换为servletRequest
     * @param fullHttpRequest
     * @return
     * @throws Exception
     */
    private MockHttpServletRequest getRequest(FullHttpRequest fullHttpRequest) throws Exception{
        ServletContext servletContext = dispatcherServlet.getServletContext();
        MockHttpServletRequest servletRequest = new MockHttpServletRequest(servletContext);

        // 复制header
        Set<String> headerNameSet = fullHttpRequest.headers().names();
        for (String name : headerNameSet) {
            for (String value : fullHttpRequest.headers().getAll(name)) {
                log.info("请求消息头{}:{}",name,value);
                servletRequest.addHeader(name,value);
            }
        }
        // 复制uri
        String uri = fullHttpRequest.uri();
        uri = new String(uri.getBytes("ISO8859-1"), "UTF-8");
        log.info("uri:{}",uri);
        uri = URLDecoder.decode(uri, "UTF-8");
        UriComponents uriComponents = UriComponentsBuilder.fromUriString(uri).build();
        String path = uriComponents.getPath();
        path = URLDecoder.decode(path, "UTF-8");
        servletRequest.setRequestURI(path);
        servletRequest.setServletPath(path);

        if(uriComponents.getScheme() != null){
            servletRequest.setScheme(uriComponents.getScheme());
        }
        if(uriComponents.getHost() != null){
            servletRequest.setServerName(uriComponents.getHost());
        }
        if(uriComponents.getPort() != -1){
            servletRequest.setServerPort(uriComponents.getPort());
        }

        Map<String, String>  parammap = getRequestParams(fullHttpRequest);

        //复制请求参数
        if (uriComponents.getQuery() != null) {
            String query = UriUtils.decode(uriComponents.getQuery(),"UTF-8");
            servletRequest.setQueryString(query);
        }
        if(parammap!=null&&parammap.size()>0){
            for (String key : parammap.keySet()) {
                servletRequest.addParameter(UriUtils.decode(key,"UTF-8"), UriUtils.decode(parammap.get(key) == null ? "": parammap.get(key), "UTF-8"));
            }
        }


        // 复制method
        servletRequest.setMethod(fullHttpRequest.method().name());
        // 复制content
        ByteBuf content = fullHttpRequest.content();
        content.readerIndex(0);
        byte[] data = new byte[content.readableBytes()];
        content.readBytes(data);
        servletRequest.setContent(data);

        // 复制query
        if(uriComponents.getQuery() != null){
            String query = UriUtils.decode(uriComponents.getQuery(),"UTF-8");
            servletRequest.setQueryString(query);
        }

        return servletRequest;
    }

    /**
     * 获取post请求、get请求的参数保存到map中
     */
    private Map<String, String> getRequestParams(HttpRequest req) throws UnsupportedEncodingException {
        Map<String, String>requestParams=new HashMap<String, String>();
        // 处理get请求
        if (req.method() == HttpMethod.GET) {
            log.info("req.uri:{}",req.uri());
            QueryStringDecoder decoder = new QueryStringDecoder(new String(req.uri().getBytes("ISO-8859-1"),"UTF-8"));
            Map<String, List<String>> parame = decoder.parameters();
            Iterator<Map.Entry<String, List<String>>> iterator = parame.entrySet().iterator();
            while(iterator.hasNext()){
                Map.Entry<String, List<String>> next = iterator.next();
                log.info("请求值{}:{}",next.getKey(),next.getValue().get(0));
                requestParams.put(next.getKey(), next.getValue().get(0));
            }
        } // 处理POST请求
        if (req.method() == HttpMethod.POST) {
            HttpPostRequestDecoder decoder = new HttpPostRequestDecoder( new DefaultHttpDataFactory(false), req);
            List<InterfaceHttpData> postData = decoder.getBodyHttpDatas();
            for(InterfaceHttpData data:postData){
                if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
                    MemoryAttribute attribute = (MemoryAttribute) data;
                    requestParams.put(attribute.getName(), attribute.getValue());
                }
            }
        }
        return requestParams;
    }


    /**
     * 封装response
     * @param httpServletResponse
     * @return
     * @throws UnsupportedEncodingException
     */
    private FullHttpResponse getResponse(MockHttpServletResponse httpServletResponse) throws UnsupportedEncodingException {

        HttpResponseStatus status = HttpResponseStatus.valueOf(httpServletResponse.getStatus());
        String result = httpServletResponse.getContentAsString();
        result = StringUtils.isEmpty(result)?"":result;
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.copiedBuffer(result, CharsetUtil.UTF_8));

        httpServletResponse.getHeaderNames()
                .stream()
                .forEach((name)->{
                    log.info("响应消息头：{}:{}",name,httpServletResponse.getHeader(name));
                    response.headers().set(name,httpServletResponse.getHeader(name));
                });
        return response;
    }
}
